'gfx editor.bas
#include once "gfxed.bi"
#include once "ext/graphics/manip.bi"
#include once "ext/graphics/bmp.bi"
#include once "ext/xml.bi"
#include once "inputex.bi"
#include once "vbcompat.bi"
#include once "fbconfig.bi"
#include once "dialogs.bi"

declare function init_grid_img( byval orig as integer, byval factor as integer ) as fb.image ptr
declare function do_save( byval s as ext.gfx.sprite ptr ) as string
declare function do_load( byval s as ext.gfx.sprite ptr, byref filetoload as string = "" ) as string
declare sub pal_switch( byval primary as uinteger ptr, byval alternate as uinteger ptr, pal_colors() as integer )
declare sub load_pal_colors( pal_colors() as integer )
declare sub animate_debug( byval dx as integer, byval dy as integer, byval i as any ptr )

config.set_app_name("mpge")
config.load()

screenres screen_x, screen_y, 32
windowtitle "Mud's Pixel Gfx Editor: " & __VERSION__ & " Build: " & hex(__WELD_BUILDN)
var imgs = new ext.gfx.Sprite[num_sprites]
var defaultmse = new ext.gfx.Sprite(4)
var mse = defaultmse
var factor = 8
var orig = 48
var x4 = orig * factor
var mcolor = rgb(0,0,0)
var hilight = imagecreate(48,48,rgb(255,255,255),32)
redim pal_color_list() as integer
load_pal_colors( pal_color_list() )

var window_close = space(2)
window_close[0] = 255
window_close[1] = asc("k")

mse->SetImage(0, imagecreate(factor, factor, mcolor,32))
line mse->getImage(0),(1,1)-(factor-2,factor-2), rgb(255,0,255),BF
for n as integer = 1 to 3
        mse->duplicateImage( 0, n )
        line mse->getImage(n),(n+1,n+1)-(factor-(n+1),factor-(n+1)), rgb(255,255,255), B
next
var mframe = 0f
var moffset = (factor/2)
for n as integer = 0 to num_sprites - 1
        imgs[n].init(1)
        imgs[n].SetImage(0, imagecreate(orig,orig, rgb(255,0,255),32))
        imgs[n].Position(n*(orig+2), x4+11)
next

var ccbox = new box
ccbox->x1=404 : ccbox->y1 = 25
ccbox->x2= 467 : ccbox->y2 = 37
var curColor = rgb(0,0,0)

var accbox = new box
accbox->x1=468 : accbox->y1=25
accbox->x2=529 : accbox->y2=37
var acurColor = rgb(255,255,255)

var curFrame = 0
var curTool = 0
var oldcurTool = curTool
var tools = load_tools()
setmouse(,,0)
var status = "Ready."

var guide = -1
var guide_img = imagecreate(orig,orig,rgb(255,0,255),32)

var snap_to = config.get_bool("snap_to_grid", ext.bool.true)

var grid = config.get_bool("show_grid", ext.bool.false)
var grid_img = init_grid_img(orig,factor)

if command() <> "" then
        var __tmp_s_c = trim(command())
        status = do_load(imgs,__tmp_s_c)
        orig = imgs[0].getImage(0)->width
        factor = x4 / orig
        imagedestroy grid_img
        grid_img = init_grid_img( orig, factor )
        imagedestroy guide_img
        guide_img = imagecreate(orig,orig,rgb(255,0,255),32)
end if

var x4_img = imagecreate(x4,x4,rgb(255,0,255),32)

#if defined(__FB_DOS__)
while not multikey(fb.SC_ESCAPE)
#else
while 1
        #endif

        if inkey() = window_close then exit while

        screenlock
        cls
        line (1,1)-(x4+3,x4+3), rgb(205,205,205), B 'box around drawing area
        paint (639,4), rgb(200,200,200), rgb(205,205,205) 'white background

        draw string (406,16), "Color",0,,trans
        draw_input(410,27,right(hex(curColor),6),ccbox) 'color text display
        line (406,37)-(467,56), curColor, BF 'color preview

        draw string (470,16), "altColor",0,,trans
        draw_input(474,27,right(hex(acurColor),6),accbox) 'alt color text display
        line (468,37)-(529,56), acurColor, BF 'alt color preview

        for n as integer = 0 to num_sprites - 1 'draw the sprite row
                imgs[n].DrawImage 0, 0, ext.gfx.DrawMethods.PsET_
        next

        line (2,2)-(x4+2,x4+2),0,BF
        var transcol = rgb(255,0,255)
        line x4_img, (0,0)-(x4-1,x4-1), transcol, BF
        var temp_image = imagecreate(orig,orig,transcol)
        'our guide at 50% visible
        
        if guide > -1 then
        
        put guide_img, (0,0), imgs[guide].getImage(0), pset
        put temp_image, (0,0), guide_img, alpha, 100
        end if

        'and the enlarged drawing area
        
        put temp_image, (0,0), imgs[curFrame].getImage(0), trans
        ext.gfx.rotozoomasm(x4_img, temp_image, 5+(orig*(factor/2)), 5+(orig*(factor/2)), 0, csng(factor), csng(factor), transcol)

        put (2,2), x4_img, PSET
        if grid then put (2,2), grid_img, trans

        'status area
        line (0, screen_y - 12)-(screen_x,screen_y), rgb(169,169,169), BF
        draw string (2, screen_y - 10), status, 0, , trans

        line (400,80)-(600,380), rgb(169,169,169), BF
        line (400,80)-(400,380), 0
        line (450,80)-(450,380), 0
        line (500,80)-(500,380), 0
        line (550,80)-(550,380), 0
        line (600,80)-(600,380), 0
        for n as integer = 80 to 380 step 50
                line(400, n)-(600, n), 0
        next

        var temp_index = 0
        for n as integer = 0 to 3
                for nx as integer = 0 to 5

                        if temp_index < num_tools then
                                put ( 402+(n*50), 82+(nx*50) ), tools[temp_index].toolbox, trans
                                if temp_index = curtool then put (402+(n*50),82+(nx*50)),hilight, alpha, 100
                                temp_index += 1
                        end if

                next
        next

        'finally our cursor
        mse->drawImage int(mframe), 0, ext.gfx.DrawMethods.TRANS_
        screenunlock

        var x = -1, y = -1, button = 0
        getmouse x, y, ,button
        'x -= moffset : y -= moffset

        mse->position( csng(x), csng(y) )


        var off_x = int(x/factor)
        if off_x > (orig-1) then off_x = (orig-1)
        var off_y = int(y/factor)
        if off_y > (orig-1) then off_y = (orig-1)

        'draw
        if x > 1 andalso x < x4+2 then
                if y > 1 andalso y < x4+2 then

                        status = "x= " & off_x & " y= " & off_y

                        if button and 1 then 'left click
                                if curTool = 10 then
                                        curColor = point(off_x,off_y,imgs[curFrame].getImage(0))
                                else
                                        tools[curTool].use( imgs[curFrame].getImage(0), off_x, off_y, curColor, @tools[curTool] )
                                end if
                        elseif button and 2 then 'right click
                                if curTool = 10 then
                                        acurColor = point(off_x,off_y,imgs[curFrame].getImage(0))
                                else
                                        tools[curTool].use( imgs[curFrame].getImage(0), off_x, off_y, acurColor, @tools[curTool] )
                                end if
                        end if
                        if snap_to then
                                mse->position( csng((off_x*factor)+(factor/2)), csng((off_y*factor)+(factor/2)) )
                        end if
                end if
        end if


        'toolbox
        if x > 400 andalso x < 600 then
                if y > 80 andalso y < 380 then

                        var computedx = (int((x-400)/50)*5)
                        var toolchooser =  computedx + int((y-80)/50)
                        toolchooser += computedx / 5
                        
                        if toolchooser < num_tools then
                                status = "Tool: " & tools[toolchooser].toolname
                                if button and 1 then
                                        select case lcase(tools[toolchooser].toolname)
                                                case "help"
                                                        dialog.message(!"Starting Browser for manual.\vUse F1 for Quick help.")
                                                        shell "start http://code.google.com/p/muds-pixel-gfxed/wiki/UserManual"
                                                        status = "Opening help website..."
                                                case "save"
                                                        status = do_save(imgs)
                                                case "load"
                                                        status = do_load(imgs)
                                                        orig = imgs[0].getImage(0)->width
                                                        factor = x4 / orig
                                                        imagedestroy grid_img
                                                        grid_img = init_grid_img( orig, factor )
                                                        imagedestroy guide_img
                                                        guide_img = imagecreate(orig,orig,rgb(255,0,255),32)
                                                        curFrame = 0
                                                        guide = -1

                                                case "colors"
                                                        pal_switch(@curColor, @acurColor, pal_color_list())
                                                        setmouse(,,0)
                                                        button = 0
                                                case "grid"
                                                        if grid then
                                                                grid = ext.bool.false
                                                        else
                                                                grid = ext.bool.true
                                                        end if
                                                case else

                                                        curTool = toolchooser
                                        end select
                                end if
                        end if

                end if
        end if

        'switch
        for n as integer = 0 to num_sprites -1
                if button and 1 then
                        if mse->isCollided(imgs[n], ext.gfx.PPOPTIONS.noPP) then
                                curFrame = n
                                status = "curframe: " & curFrame
                                exit for
                        end if
                end if
        next

        'debug
        if multikey(fb.SC_F7) then
                status = "x= " & x & " y= " & y & " g= " & guide & " f= " & curFrame
        end if

        if multikey(fb.SC_F4) then
                if dialog.question(!"Hello Mr Spiffy.\vDo you want to play a game?",, dialog.icon.questionmark ) = dialog.response.yes then
                        var x__x__ = dialog.input_str("Please enter your name.")
                        var y_cancel = 0
                        var y__y__ = dialog.input_int("Please enter your age.", @y_cancel)
                        dialog.message("Well, " & x__x__ & !", it seems\v" & y__y__ & " isn't old enough to play.", dialog.icon.warning, "Shucks")
                end if
        end if
        if multikey(fb.SC_F5) then
                var delcancel = 0
                var delay_anim = dialog.input_int(!"Delay in ms\vbetween frames?",@delcancel, dialog.icon.questionmark)
                if delcancel = 1 then delay_anim = 25
                var dblDelay = delay_anim / 100
                dialog.custom_ok( orig, orig, dblDelay, @animate_debug, imgs )
        end if

        if multikey(fb.SC_F1) then
                dialog.message( !"Quick Help\vKeyboard Shortcuts:\vP - Pen\vF - Fill\vL - Line\vC - Circle\vB - Box\v[ - Left Guide\v] - Right Guide")
        end if

        if multikey(fb.SC_P) then
                curTool = 0
                status = "Active Tool: " & tools[curTool].toolname
        end if

        if multikey(fb.SC_F) then
                curTool = 1
                status = "Active Tool: " & tools[curTool].toolname
        end if

        if multikey(fb.SC_L) then
                curTool = 2
                status = "Active Tool: " & tools[curTool].toolname
        end if

        if multikey(fb.SC_C) then
                curTool = 3
                status = "Active Tool: " & tools[curTool].toolname
        end if

        if multikey(fb.SC_B) then
                curTool = 4
                status = "Active Tool: " & tools[curTool].toolname
        end if

        if multikey(fb.SC_LEFTBRACKET) andalso curframe > 0 then
                if guide = curframe - 1 then
                        guide = -1
                else
                        guide = curframe - 1
                end if
                status = "guide: " & guide
        end if

        if multikey(fb.SC_RIGHTBRACKET) andalso curframe < (num_sprites-1) then
                if guide = curframe + 1 then
                        guide = -1
                else
                        guide = curframe + 1
                end if
                status = "guide: " & guide
        end if

        'tool switcher
        if curTool <> oldcurTool then
                if tools[curTool].cursor <> 0 then
                        mse = tools[curTool].cursor
                else
                        mse = defaultmse
                end if
                mframe = 0
                tools[oldcurTool].destroy(@tools[oldcurTool])
                oldcurTool = curTool
        end if

        sleep 5,1
        mframe += .05 : if mframe > mse->Count - 1 then mframe = 0
wend

setmouse(,,1)
sleep 1,1
config.set_bool("show_grid",grid)
config.set_integer_array("palette","color", pal_color_list() )
config.save()
delete ccbox
delete accbox
delete[] imgs
delete[] tools
delete defaultmse
imagedestroy hilight

''END MAIN

sub animate_debug( byval dx as integer, byval dy as integer, byval i as any ptr )
        static as integer n = 0
        var im = cast(ext.gfx.sprite ptr, i)
        put (dx,dy), im[n].getImage(0), PSET
        n += 1
        if n > 11 then n = 0
end sub

function init_grid_img( byval orig as integer, byval factor as integer ) as fb.image ptr
        var ret = imagecreate(orig*factor,orig*factor,rgb(255,0,255),32)
        for n as integer = factor to (orig*factor) step factor
                line ret,(0,n)-(orig*factor,n),rgb(200,200,200)
                line ret,(n,0)-(n,orig*factor),rgb(200,200,200)
        next
        return ret
end function

function do_save( byval s as ext.gfx.sprite ptr ) as string

        var fn = dialog.input_str("Enter filename to save to:")
        if fn = chr(27) then return "Save cancelled!"
        if right(fn,4) <> ".bmp" then fn = fn & ".bmp"
        if fn = ".bmp" then return "Save cancelled!"
        if fileexists(fn) then
                var resp = dialog.question(!"That file already exists.\vWould you like to overwrite it?",,dialog.icon.warning)
                if resp = dialog.response.no then return "Save cancelled!"
        end if
        savestep2:
        var save_f_c = 0
        var save_f = dialog.input_int(!"Number of frames\vto save? [1 to 12]",@save_f_c)
        if save_f_c = 1 then return "Save Cancelled!"
        if save_f < 1 orelse save_f > 12 then goto savestep2

        var temp_i = imagecreate(s[0].getImage(0)->width*save_f,s[0].getImage(0)->height)

        for n as integer = 0 to save_f - 1
                put temp_i,(n*s[0].getImage(0)->width,0), s[n].getImage(0), PSET
        next

        bsave fn, temp_i

        imagedestroy temp_i

        return "Saved as " & fn

end function

function do_load( byval s as ext.gfx.sprite ptr, byref filetoload as string = "" ) as string


        var fn = ""
        if len(filetoload) = 0 then
                fn = dialog.input_str("Enter Filename to Load:")
                if fn = chr(27) then return "Loading Cancelled!"
                if right(fn,4) <> ".bmp" then fn = fn & ".bmp"
                if fn = ".bmp" then return "Loading Cancelled!"
        else
                fn = filetoload
        end if
        if not fileexists(fn) then
                dialog.message( !"Error\vThe file you chose:\v" & fn & !"\vdoes not exist in the\vlocation you specified." )
                return "File does not exist!"
        end if
        cls
        var temp_p = ext.gfx.bmp.load(fn)
        put (0,0), temp_p, PSET
        loadstep2:
        var load_n_c = 0
        var load_n = dialog.input_int(!"Number of frames\vto load? [1 to 12]", @load_n_c)
        if load_n_c = 1 then
                imagedestroy( temp_p )
                return "Loading Cancelled!"
        end if
        if load_n < 1 orelse load_n > 12 then goto loadstep2

        var load_s_c = 0
        var load_s = dialog.input_int(!"What is the dimensions of your sprite?\vE.G. Sprite is 48x48 enter 48.",@load_s_c)
        if load_s_c = 1 then
                imagedestroy( temp_p )
                return "Loading at dimensions cancelled."
        end if
        if load_s < 8 then
                dialog.message( !"Oops, Minimum dimensions is 8x8", dialog.icon.warning )
                imagedestroy( temp_p )
                return "Invalid dimensions given."
        end if

        'step 4
        load_s_c = 0
        var load_x = dialog.input_int(!"What x coordinate does your sprite start at?\v0 is top left.",@load_s_c)
        if load_s_c = 1 then
                imagedestroy( temp_p )
                return "Loading at x coord cancelled."
        end if

        load_s_c = 0
        var load_y = dialog.input_int(!"What y coordinate does your sprite start at?\v0 is top left.",@load_s_c)
        if load_s_c = 1 then
                imagedestroy( temp_p )
                return "Loading at y coord cancelled."
        end if

        load_s_c = 0
        var load_sp = dialog.input_int(!"Is there any space between sprites?\v(in pixels)",@load_s_c)
        if load_s_c = 1 then
                imagedestroy( temp_p )
                return "Loading cancelled at space between sprites."
        end if

        var temp_i = new ext.gfx.sprite

        temp_i->init(load_n+1)

        var error_load = temp_i->fromSpriteSheet(temp_p,load_x,load_y,load_s,load_s,load_sp,load_n)

        if error_load < load_n then
                imagedestroy temp_p
                delete temp_i
                dialog.message( !"Oops!\vThere was an error loading\vthe image you gave.\vMake sure you have the\vframe count correct then\vcheck the User Manual\vfor details on what is\vsupported." )
                return "Error"
        end if

        for n as integer = 0 to load_n - 1
                var temp_img = imagecreate(temp_i->getImage(n)->width,temp_i->getImage(n)->height)
                put temp_img,(0,0),temp_i->getImage(n),PSET
                s[n].replaceImage(0, temp_img)
        next

        if load_n < 12 then
                for n as integer = load_n+1 to 12
                        var temp_img = imagecreate(temp_i->getImage(0)->width,temp_i->getImage(0)->height)
                        s[n-1].replaceImage(0, temp_img)
                next
        end if

        delete temp_i
        imagedestroy temp_p

        return "Loaded " & fn

end function

sub pal_switch( byval primary as uinteger ptr, byval alternate as uinteger ptr, pal_colors() as integer )
        var curSel = 0
        setmouse(,,1)
        dim as InputEx chooseCLR
        chooseCLR.maxlength=6
        chooseCLR._print_cb= @draw_input
        chooseCLR._print_cb_data = new box
        with *cast(box ptr, chooseCLR._print_cb_data)
                .x1 = 481 : .y1 = 361
                .x2 = 559 : .y2 = 369
        end with

        do until multikey(fb.sc_x)
                var x = -1, y = -1, button = 0
                getmouse x, y, ,button
                screenlock
                'dialog
                line (470,250)-(570,410),rgb(200,200,200),BF
                line (470,250)-(570,410),rgb(250,250,250),B

                'colors
                for n as integer = 0 to 7
                        line (480,250+(n+1)*10)-(510,260+(n+1)*10),pal_colors(n), BF
                next n
                for n as integer = 8 to 15
                        line (530,250+(n-7)*10)-(560,260+(n-7)*10),pal_colors(n), BF
                next n
                'current selection
                line (480,340)-(560,360),pal_colors(curSel), BF
                'hex value / custom
                line (480,360)-(560,370),0,B
                draw string (496,362),right(hex(pal_colors(curSel)),6),0,,trans

                'set buttons
                line (480,375)-(510,390),0,B
                draw string (485,380),"PRI",0,,trans
                line (530,375)-(560,390),0,B
                draw string (535,380),"ALT",0,,trans

                'close button
                line (510,395)-(530,410),0,B
                draw string (517,399),"X",0,,trans

                screenunlock

                if button and 1 then
                        'close
                        if x > 510 andalso x < 530 andalso y > 395 andalso y < 410 then
                                sleep 10,1
                                return
                        end if
                        'set pri (480,375)-(510,390)j
                        if x > 480 andalso x < 510 andalso y > 375 andalso y < 390 then
                                *primary = pal_colors(curSel)
                                return
                        end if
                        'set alt (530,375)-(560,390)
                        if x > 530 andalso x < 560 andalso y > 375 andalso y < 390 then
                                *alternate = pal_colors(curSel)
                                return
                        end if
                        'custom (480,360)-(560,370)
                        if x > 480 andalso x < 560 andalso y > 360 andalso y < 370 then
                                pal_colors(curSel) = valuint("&hFF" & chooseCLR.get(496,362))
                        end if
                        'colors left
                        if x > 479 andalso x < 511 andalso y > 249 andalso y < 340 then
                                curSel = int((y - 251) / 10) - 1
                        end if
                        'colors right
                        if x > 529 andalso x < 561 andalso y > 249 andalso y < 340 then
                                curSel = int((y - 251) / 10) + 7
                        end if
                end if

                sleep 1,1
        loop
end sub

sub load_pal_colors( ret() as integer )

        redim ret(0 to 15)

        #define _rgb(r,g,b) cint(rgb(r,g,b))
        ret(0) = _rgb(0,0,0) ' black
        ret(1) = _rgb(&hDC,0,0) 'red
        ret(2) = _rgb(0,&h84,&hc8) 'blue
        ret(3) = _rgb(0,&h91,0) 'green
        ret(4) = _rgb(200,200,200) ' gray
        ret(5) = _rgb(255,255,0) ' yellow
        ret(6) = _rgb(0,255,255) 'sky blue
        ret(7) = _rgb(100,0,200) 'purple
        ret(8) = _rgb(255,255,255) 'white
        ret(9) = _rgb(&hb5,0,0) 'dark red
        ret(10) = _rgb(0,&h5c,&h94) 'dark blue
        ret(11) = _rgb(50,&h66,0) 'dark green
        ret(12) = _rgb(100,100,100) 'dark gray
        ret(13) = _rgb(180,180,0) ' dark yellow
        ret(14) = _rgb(0,150,150)
        ret(15) = _rgb(20,30,60) 'dark purple

end sub
